using System;
using System.Reflection;
using System.Runtime.Serialization;

namespace Voodoo.Utils
{
	public static class ObjectExtension
	{
		public static object DeepCopy(this object obj)
		{
			if (obj == null)
			{
				return null;
			}
			Type type = obj.GetType();
			if (type.IsValueType || type == typeof(string))
			{
				return obj;
			}
			if (type.IsArray)
			{
				Type type2 = Type.GetType(type.FullName.Replace("[]", string.Empty));
				Array array = obj as Array;
				Array array2 = Array.CreateInstance(type2, array.Length);
				for (int i = 0; i < array.Length; i++)
				{
					array2.SetValue(array.GetValue(i).DeepCopy(), i);
				}
				return Convert.ChangeType(array2, obj.GetType());
			}
			if (type.IsClass)
			{
				object uninitializedObject = FormatterServices.GetUninitializedObject(type);
				FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					object value = fieldInfo.GetValue(obj);
					if (value != null)
					{
						fieldInfo.SetValue(uninitializedObject, value.DeepCopy());
					}
				}
				return uninitializedObject;
			}
			throw new ArgumentException("Unknown type");
		}
	}
}
